
// Copyright (C) 2007 Richard Uhler
// This file is part of Esiply.
//
// Esiply is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License, Version 2,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

#include "FormalParameterList.h"
#include "FunctionExpression.h"
#include "Null.h"
#include "Object.h"
#include "RegularFunction.h"
#include "Scope.h"
#include "SourceElements.h"
#include "String.h"
#include "Value.h"
#include "ValueType.h"

FunctionExpression::FunctionExpression(String* identifier,
        FormalParameterList* params, SourceElements* body,int sync)
    : m_identifier(identifier), m_params(params), m_body(body),m_sync(sync)
{}

Value* FunctionExpression::evaluate(Scope* scope)
{
    // Ecma 13
    // This implementation mixes both the case of an included
    // identifier, and the case of a missing one. So it doesn't
    // line up just right with what Ecma says.
    Object* obj = NULL;
    Scope* fscope = scope;
    if (m_identifier)
    {
        // 1. Create a new object as if by the expression new Object;
        obj = new Object();

        // 2. Add obj to the front of the scope chain.
        // TODO: what should 'this' be?
        fscope = new Scope(scope, obj, Object::global);
    }

    // 3. Create a new Function object as specified in 13.2 with
    // the given information.
    RegularFunction* func = new RegularFunction(fscope,
            m_params->as_string()->string()->c_str(), m_body);
    // TODO: function should set it's own prototype
    func->set_prototype(Function::prototype);
	//add Synchronized support
	if(m_sync == 1){
		func->set_sync(1);
	}else{
		func->set_sync(0);
	}
    if (m_identifier)
    {
        // 4. Create a property in the obj whose name is
        // identifier, value is func, attributes {DontDelete, ReadOnly}
        obj->object()->put(m_identifier, func, PA_DONT_DELETE | PA_READ_ONLY);

        // 5. Remove Result(1) from the scope chain.
        // (nothing to do)
    }

    // 6. Return func
    return func;
}

int FunctionExpression::get_sync() const
{
	return  m_sync;
}
